﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;

namespace YJKCoordinate
{
	public class ArcAngleCornerCurveMaker : IMakeCornerCurves
	{
		private ArcAngleCornerCurveMaker()
		{
		}

		public static ArcAngleCornerCurveMaker GetSingleChamferCornerCurveMaker()
		{
			if (ArcAngleCornerCurveMaker.singleTag == null)
			{
				ArcAngleCornerCurveMaker.singleTag = new ArcAngleCornerCurveMaker();
			}
			return ArcAngleCornerCurveMaker.singleTag;
		}

		public List<Curve> GetCornerBoundryCurves(ThreeInputDataPacker input, out XYZ startPoint_Mid, out XYZ endPoint_Mind)
		{
			List<Curve> list = new List<Curve>();
			List<Curve> list2;
			List<Curve> list3;
			Utiltiy.GetInnerIntersectionPoint(input.GetTwoInputData(0), input.GetTwoInputData(1), out list2, out list3);
			XYZ xyz;
			XYZ xyz2;
			XYZ xyzpoint;
			XYZ xyzpoint2;
			bool cornernRectangle = Utiltiy.GetCornernRectangle(input, out xyz, out xyz2, out xyzpoint, out xyzpoint2);
			if (cornernRectangle)
			{
				return this.getCornerBoundryCurvesForShapeChange(input, out startPoint_Mid, out endPoint_Mind);
			}
			XYZ xyz3 = Utiltiy.GetMidPoint(input.GetDriection(0), input.GetDriection(1)).Normalize();
			double num = input.GetDriection(0).AngleTo(xyz3);
			double num2 = input.GetDriection(1).AngleTo(xyz3);
			if (num > Math.PI*.5)
			{
				num = Math.PI - num;
			}
			if (num2 > Math.PI*.5)
			{
				num2 = Math.PI - num2;
			}
			double num3 = input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Radius];
			XYZ xyz4 = xyz.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num3));
			XYZ xyz5 = xyz.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num3));
			xyzpoint = list2[1].Project(xyz4).XYZPoint;
			xyzpoint2 = list3[1].Project(xyz5).XYZPoint;
			XYZ pointOnArcByTwoArcOneArc = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz4, xyz5, num3, input.GetDriection(0), null, null);
			xyz4.Add(-xyz).Normalize();
			XYZ driection = input.GetDriection(0);
			XYZ driection2 = input.GetDriection(1);
			double num4 = xyzpoint.DistanceTo(xyz2);
			double num5 = Math.Tan(num) * num4;
			XYZ pointOnArcByTwoArcOneArc2 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyzpoint, xyzpoint2, num5, driection, driection2, null);
			startPoint_Mid = xyz4.Add(xyzpoint).Divide(2.0);
			endPoint_Mind = xyz5.Add(xyzpoint2).Divide(2.0);
			if (input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width] == input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width])
			{
				list.Add(Arc.Create(xyz4, xyz5, pointOnArcByTwoArcOneArc));
				list.Add(Line.CreateBound(xyz5, xyzpoint2));
				list.Add(Arc.Create(xyzpoint2, xyzpoint, pointOnArcByTwoArcOneArc2));
				list.Add(Line.CreateBound(xyzpoint, xyz4));
				if (Utiltiy.CheckNoneEndInterintersection(list))
				{
					throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
				}
				return list;
			}
			else
			{
				XYZ avectorAnotherXY = Utiltiy.GetAVectorAnotherXY(Utiltiy.GetMidPoint(input.GetDriection(0), input.GetDriection(1)).Normalize());
				Line line = Line.CreateUnbound(xyz2, avectorAnotherXY);
				if (input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width] > input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width])
				{
					Line line2 = Line.CreateBound(xyz4, xyzpoint);
					XYZ xyz6 = xyzpoint;
					line2.MakeUnbound();
					IntersectionResultArray intersectionResultArray;
					SetComparisonResult setComparisonResult = line.Intersect(line2, out intersectionResultArray);
					if (8 != (int)setComparisonResult)
					{
						throw new CornerMakerException(StaticRescource.StrNonIntersection);
					}
					XYZ xyzpoint3 = intersectionResultArray.get_Item(0).XYZPoint;
					num5 = xyz6.DistanceTo(xyzpoint3);
					XYZ xyz7 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num5));
					XYZ pointOnArcByTwoArcOneArc3 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz6, xyz7, num5, input.GetDriection(0), input.GetDriection(1), null);
					list.Add(Arc.Create(xyz4, xyz5, pointOnArcByTwoArcOneArc));
					list.Add(Line.CreateBound(xyz5, xyzpoint2));
					list.Add(Line.CreateBound(xyzpoint2, xyz7));
					list.Add(Arc.Create(xyz7, xyz6, pointOnArcByTwoArcOneArc3));
					list.Add(Line.CreateBound(xyz6, xyz4));
					if (Utiltiy.CheckNoneEndInterintersection(list))
					{
						throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
					}
					return list;
				}
				else
				{
					Line line2 = Line.CreateBound(xyz5, xyzpoint2);
					XYZ xyz7 = xyzpoint2;
					line2.MakeUnbound();
					IntersectionResultArray intersectionResultArray;
					SetComparisonResult setComparisonResult = line.Intersect(line2, out intersectionResultArray);
					if (8 != (int)setComparisonResult)
					{
						throw new CornerMakerException(StaticRescource.StrNonIntersection);
					}
					XYZ xyzpoint3 = intersectionResultArray.get_Item(0).XYZPoint;
					num5 = xyz7.DistanceTo(xyzpoint3);
					XYZ xyz6 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num5));
					XYZ pointOnArcByTwoArcOneArc3 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz6, xyz7, num5, input.GetDriection(0), input.GetDriection(1), null);
					list.Add(Arc.Create(xyz5, xyz4, pointOnArcByTwoArcOneArc));
					list.Add(Line.CreateBound(xyz4, xyzpoint));
					list.Add(Line.CreateBound(xyzpoint, xyz6));
					list.Add(Arc.Create(xyz6, xyz7, pointOnArcByTwoArcOneArc3));
					list.Add(Line.CreateBound(xyzpoint2, xyz5));
					if (Utiltiy.CheckNoneEndInterintersection(list))
					{
						throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
					}
					return list;
				}
			}
		}

		private List<Curve> getCornerBoundryCurvesForShapeChange(ThreeInputDataPacker input, out XYZ startPoint_Mid, out XYZ endPoint_Mid)
		{
			List<Curve> list = new List<Curve>();
			List<Curve> list2;
			List<Curve> list3;
			Utiltiy.GetInnerIntersectionPoint(input.GetTwoInputData(0), input.GetTwoInputData(1), out list2, out list3);
			XYZ xyz;
			XYZ xyz2;
			XYZ xyzpoint;
			XYZ xyzpoint2;
			Utiltiy.GetCornernRectangle(input, out xyz, out xyz2, out xyzpoint, out xyzpoint2);
			XYZ xyz3 = Utiltiy.GetMidPoint(input.GetDriection(0), input.GetDriection(1)).Normalize();
			double num = input.GetDriection(0).AngleTo(xyz3);
			double num2 = input.GetDriection(1).AngleTo(xyz3);
			if (num > Math.PI*.5)
			{
				num = Math.PI - num;
			}
			if (num2 > Math.PI*.5)
			{
				num2 = Math.PI - num2;
			}
			double num3 = input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Radius];
			XYZ xyz4 = xyz.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num3));
			XYZ xyz5 = xyz.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num3));
			Curve curve = Line.CreateBound(list2[1].GetEndPoint(0), list2[1].GetEndPoint(1));
			curve.MakeUnbound();
			Curve curve2 = Line.CreateBound(list3[1].GetEndPoint(0), list3[1].GetEndPoint(1));
			curve2.MakeUnbound();
			xyzpoint = curve.Project(xyz4).XYZPoint;
			xyzpoint2 = curve2.Project(xyz5).XYZPoint;
			XYZ pointOnArcByTwoArcOneArc = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz4, xyz5, num3, input.GetDriection(0), null, null);
			startPoint_Mid = xyz4.Add(xyzpoint).Divide(2.0);
			endPoint_Mid = xyz5.Add(xyzpoint2).Divide(2.0);
			if (input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width] > input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width])
			{
				if (Line.CreateBound(xyzpoint, xyz2).Direction.Normalize().IsAlmostEqualTo(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0))))
				{
					double num4 = num3 + input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width];
					XYZ xyz6 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num4));
					XYZ xyz7 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num4));
					XYZ pointOnArcByTwoArcOneArc2 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz6, xyz7, num4, input.GetDriection(0), input.GetDriection(1), null);
					XYZ xyzpoint3 = list2[0].Project(xyz6).XYZPoint;
					list.Add(Arc.Create(xyz4, xyz5, pointOnArcByTwoArcOneArc));
					list.Add(Line.CreateBound(xyz5, xyzpoint2));
					list.Add(Line.CreateBound(xyzpoint2, xyz7));
					list.Add(Arc.Create(xyz7, xyz6, pointOnArcByTwoArcOneArc2));
					list.Add(Line.CreateBound(xyz6, xyzpoint3));
					list.Add(Line.CreateBound(xyzpoint3, xyz4));
					startPoint_Mid = xyzpoint3.Add(xyz6).Divide(2.0);
					endPoint_Mid = xyz5.Add(xyzpoint2).Divide(2.0);
					if (Utiltiy.CheckNoneEndInterintersection(list))
					{
						throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
					}
					return list;
				}
				else
				{
					double num4 = num3 + input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width];
					XYZ xyz8 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num4));
					XYZ xyz9 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num4));
					XYZ pointOnArcByTwoArcOneArc2 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz8, xyz9, num4, input.GetDriection(0), input.GetDriection(1), null);
					XYZ xyzpoint4 = list2[0].Project(xyz8).XYZPoint;
					list.Add(Arc.Create(xyz4, xyz5, pointOnArcByTwoArcOneArc));
					list.Add(Line.CreateBound(xyz5, xyzpoint2));
					list.Add(Line.CreateBound(xyzpoint2, xyz9));
					list.Add(Arc.Create(xyz9, xyz8, pointOnArcByTwoArcOneArc2));
					list.Add(Line.CreateBound(xyz8, xyzpoint4));
					list.Add(Line.CreateBound(xyzpoint4, xyz4));
					startPoint_Mid = xyzpoint4.Add(xyz8).Divide(2.0);
					endPoint_Mid = xyz5.Add(xyzpoint2).Divide(2.0);
					if (Utiltiy.CheckNoneEndInterintersection(list))
					{
						throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
					}
					return list;
				}
			}
			else
			{
				if (input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width] >= input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width])
				{
					throw new CornerMakerException(StaticRescource.StrDontWantIf);
				}
				if (Line.CreateBound(xyzpoint2, xyz2).Direction.Normalize().IsAlmostEqualTo(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1))))
				{
					double num4 = num3 + input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width];
					XYZ xyz10 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num4));
					XYZ xyz11 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num4));
					XYZ pointOnArcByTwoArcOneArc2 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz10, xyz11, num4, input.GetDriection(0), input.GetDriection(1), null);
					XYZ xyzpoint5 = list3[0].Project(xyz11).XYZPoint;
					list.Add(Arc.Create(xyz5, xyz4, pointOnArcByTwoArcOneArc));
					list.Add(Line.CreateBound(xyz4, xyzpoint));
					list.Add(Line.CreateBound(xyzpoint, xyz10));
					list.Add(Arc.Create(xyz10, xyz11, pointOnArcByTwoArcOneArc2));
					list.Add(Line.CreateBound(xyz11, xyzpoint5));
					list.Add(Line.CreateBound(xyzpoint5, xyz5));
					startPoint_Mid = xyz4.Add(xyzpoint).Divide(2.0);
					endPoint_Mid = xyzpoint5.Add(xyz11).Divide(2.0);
					if (Utiltiy.CheckNoneEndInterintersection(list))
					{
						throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
					}
					return list;
				}
				else
				{
					double num4 = num3 + input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width];
					XYZ xyz12 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(0)).Multiply(Math.Tan(Math.PI*.5 - num) * num4));
					XYZ xyz13 = xyz2.Add(Utiltiy.GetAVectorAnotherXY(input.GetDriection(1)).Multiply(Math.Tan(Math.PI*.5 - num2) * num4));
					XYZ pointOnArcByTwoArcOneArc2 = Utiltiy.GetPointOnArcByTwoArcOneArc(xyz12, xyz13, num4, input.GetDriection(0), input.GetDriection(1), null);
					XYZ xyzpoint6 = list3[0].Project(xyz13).XYZPoint;
					list.Add(Arc.Create(xyz5, xyz4, pointOnArcByTwoArcOneArc));
					list.Add(Line.CreateBound(xyz4, xyzpoint));
					list.Add(Line.CreateBound(xyzpoint, xyz12));
					list.Add(Arc.Create(xyz12, xyz13, pointOnArcByTwoArcOneArc2));
					list.Add(Line.CreateBound(xyz13, xyzpoint6));
					list.Add(Line.CreateBound(xyzpoint6, xyz5));
					startPoint_Mid = xyz4.Add(xyzpoint).Divide(2.0);
					endPoint_Mid = xyzpoint6.Add(xyz13).Divide(2.0);
					if (Utiltiy.CheckNoneEndInterintersection(list))
					{
						throw new CornerMakerException(StaticRescource.StrError_cornerLineIntersection);
					}
					return list;
				}
			}
		}

		private static ArcAngleCornerCurveMaker singleTag;
	}
}
